package TS::EIT;

use strict;
use Scalar::Util qw(weaken);

use constant TABLE_MYSTREAM_NOW_NEXT => 0x4E;
use constant TABLE_NULL => 0xFF;

use constant SECTION_NOW => 0;
use constant SECTION_NEXT => 1;
use constant SECTION_SCHEDULE => 2;

sub new {
	my($pkg, $buffer) = @_;

	my $hash = {
		buffer => $buffer,

		table_id => undef,
		section_syntax_indicator => undef,
		private_indicator => undef,
		section_length => undef,
		service_id => 0,
		version_number => 0,
		current_next_indicator => 0,
		section_number => 0,
		last_section_number => 0,
		transport_stream_id => undef,
		original_network_id => undef,
		segment_last_section_number => undef,
		last_table_id => undef,
		event => [],
		CRC_32 => undef,
	};

	my $s = bless $hash, $pkg;

	weaken($s->{buffer});
	$s->parse();

	return $s;
}

sub parse {
	my($s) = @_;

	$s->{table_id} = $s->{buffer}->getInt();

	if ($s->{table_id} == TABLE_MYSTREAM_NOW_NEXT) {
		$s->mystream_now_next();
	} elsif ($s->{table_id} == TABLE_NULL) {
		$s->{buffer}->reset();
	} else {
		printf "#### no support table_id: 0x%02x\n", $s->{table_id};
#		exit;
	}
}

sub mystream_now_next {
	my($s) = @_;

	my $a = $s->{buffer}->getInt();
	my $b = $s->{buffer}->getInt();
	$s->{section_syntax_indicator}	= $a >> 7 & 0x01;
	$s->{private_indicator}			= $a >> 6 & 0x01;
	$s->{section_length}			= ($a & 0x0F) << 8 | $b;
	my $program_endbyte = $s->{buffer}->{pos} + $s->{section_length};

	if ($s->{section_syntax_indicator}) {
		$s->{service_id} = $s->{buffer}->getShort();

		my $a = $s->{buffer}->getInt();
		$s->{version_number} = $a >> 1 & 0x1F;
		$s->{current_next_indicator} = $a & 0x01;

		$s->{section_number} = $s->{buffer}->getInt();
		$s->{last_section_number} = $s->{buffer}->getInt();
	}

	$s->{transport_stream_id} = $s->{buffer}->getShort();
	$s->{original_network_id} = $s->{buffer}->getShort();
	$s->{segment_last_section_number} = $s->{buffer}->getInt();
	$s->{last_table_id} = $s->{buffer}->getInt();

	while ($s->{buffer}->{pos} + 11 < $program_endbyte - 4) {
		push(@{$s->{event}}, $s->event());
	}

	$s->{CRC_32} = $s->{buffer}->getLong();

	$s->{buffer}->{pos} = $program_endbyte;
}

sub event {
	my($s) = @_;

	my $ret = {};

	$ret->{event_id} = $s->{buffer}->getShort();

	my $mjd = $s->{buffer}->getShort();
	my $yy = int(($mjd - 15078.2) / 365.25);
	my $mm = int(($mjd - 14956.1 - int($yy * 365.25)) / 30.6001);
	my $dd = int($mjd - 14956 - int($yy * 365.25) - int($mm * 30.6001));

	if (13 < $mm) {
		$yy = $yy + 1;
		$mm = $mm - 12;
	}

	$yy = $yy + 1900;
	$mm = $mm - 1;

	my $ch = $s->{buffer}->getInt();
	my $ci = $s->{buffer}->getInt();
	my $cs = $s->{buffer}->getInt();
#	my $hh = (($ch >> 4) & 0x0F) * 10 + ($ch & 0x0F);
#	my $ii = (($ci >> 4) & 0x0F) * 10 + ($ci & 0x0F);
#	my $ss = (($cs >> 4) & 0x0F) * 10 + ($cs & 0x0F);
	$ret->{start_time} = sprintf("%04d-%02d-%02d %02x:%02x:%02x", $yy, $mm, $dd, $ch, $ci, $cs);

	my $ch = $s->{buffer}->getInt();
	my $ci = $s->{buffer}->getInt();
	my $cs = $s->{buffer}->getInt();
#	my $hh = (($ch >> 4) & 0x0F) * 10 + ($ch & 0x0F);
#	my $ii = (($ci >> 4) & 0x0F) * 10 + ($ci & 0x0F);
#	my $ss = (($cs >> 4) & 0x0F) * 10 + ($cs & 0x0F);
	$ret->{duration} = sprintf("%02x:%02x:%02x", $ch, $ci, $cs);

	my $a = $s->{buffer}->getInt();
	my $b = $s->{buffer}->getInt();
	$ret->{running_status} = $a >> 5 & 0x07;
	$ret->{free_CA_mode} = $a >> 4 & 0x01;
	$ret->{descriptors_loop_length} = ($a & 0x0F) << 8 | $b;
	my $descriptor_loop_endbyte = $s->{buffer}->{pos} + $ret->{descriptors_loop_length};

	$ret->{descriptor} = [];

	while ($s->{buffer}->{pos} < $descriptor_loop_endbyte) {
		push(@{$ret->{descriptor}}, TS::Descriptor::parse($s->{buffer}));
	}

	$s->{buffer}->{pos} = $descriptor_loop_endbyte;

	return $ret;
}

1;
